﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Firefly.Libs;
using Jitter.LinearMath;
using Ether;
using Ether.Libs;
using Ether.Mapping;
using Jitter;

namespace Ether
{
    public sealed class StructureBank : GameComponent
    {
        //Fields 
        private Dictionary<string, Func<Structure>> towerConstructFuncs;
        public Structure CurrentBlueprint
        {
            get;
            internal set;
        }
        private string currentBlueprintID = null;

        public LevelMap ParentMap;
        public World GameWorld;

        //Construct
        public StructureBank(Game game,LevelMap map, World gameWorld)
            : base(game)
        {
            this.ParentMap = map;
            this.GameWorld = gameWorld;

            towerConstructFuncs = new Dictionary<string, Func<Structure>>();
            Add("Test", new Func<Structure>(buildTestStructure));
            Add("Nether", new Func<Structure>(buildNetherPortal));
            Add("Nexus", new Func<Structure>(buildNexusPortal));
        }

        //Methods
        public void Add(string id, Func<Structure> constructFunc)
        {
            this.towerConstructFuncs.Add(id, constructFunc);
        }

        public void SelectTower(string id)
        {
            if (!towerConstructFuncs.ContainsKey(id))
                throw new Exception("Fatal Error: Tower id='" +towerConstructFuncs + "' doesnt exist");

            currentBlueprintID = id;
            CurrentBlueprint = towerConstructFuncs[id].Invoke();
            CurrentBlueprint.LoadStructure(Game);
            CurrentBlueprint.ParentMap.BuildModeHilight();
        }
        public void Deselect()
        {
            CurrentBlueprint.ParentMap.ClearBuildModeHilighting();
            CurrentBlueprint = null;
            currentBlueprintID = null;
        }

        public void DebugRender(DebugDrawer dDrawer)
        {
            if (CurrentBlueprint != null)
                dDrawer.DrawAabb(CurrentBlueprint.Body.BoundingBox.Min, CurrentBlueprint.Body.BoundingBox.Max, Color.Blue);
        }
        public void Render(Camera camera, GameTime time)
        {
            if (CurrentBlueprint != null)
                CurrentBlueprint.DrawStructure(camera, time);
        }
        public void UpdateStructureBank(Input input, GameTime time)
        {
            if (CurrentBlueprint != null)
            {
                EtherPosition mousePosition = SelectionEngine.HoverEtherPosition;

                //Update its position
                CurrentBlueprint.Body.Position = Conversion.ConvertVect(mousePosition.ToWorldSpace());

                if (input.IsLeftClick())
                {
                    Point clickPoint = Conversion.ToPoint(Conversion.MapTo2D(mousePosition.ToWorldSpace()));

                    //Player Left clicks
                    if (SelectionEngine.CurrentHover > -1) //TODO: BUILD AVALIBILITY
                    {
                        //Create a new tower
                        Structure str = towerConstructFuncs[currentBlueprintID].Invoke();
                        str.LoadStructure(Game);
                        str.ChangeToTextureRender();
                        str.Body.Position = CurrentBlueprint.Body.Position + new JVector(0, 1, 0);

                        Point pos = Conversion.ToPoint(Conversion.MapTo2D(Conversion.ConvertVect(CurrentBlueprint.Body.Position)));

                        str.ParentMap[mousePosition.S][pos.Y, pos.X].Structure = str;
                        str.ParentWorld.AddBody(str.Body);

                        Deselect();                        
                    }
                }
            }
        }

        #region Structure building Funcs
        private TestStructure buildTestStructure()
        {
            return new TestStructure(ParentMap, GameWorld);
        }
        private NetherPortal buildNetherPortal()
        {
            return new NetherPortal(ParentMap, GameWorld);
        }
        private NexusPortal buildNexusPortal()
        {
            return new NexusPortal(ParentMap, GameWorld);
        }
        #endregion
    }
}

